grammar ascii2mathml;

@header {
package ascii2mathmlconverter.analyzer;
}

@lexer::header {
package ascii2mathmlconverter.analyzer;
}

s returns [String trad]
	:	exp {
		$trad = "<math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n" + $exp.trad + "</math>";
	}
	;

exp returns [String trad]
	:	t1=term {
			$trad = $t1.trad;
		} (ADDOP {
			String pre = "<apply>\n";
			String post = "</apply>\n";
			if ($ADDOP.text.equals("+")) {
				pre += "<plus />\n";
			} else {
				pre += "<minus />\n";
			}
		} t2=term {
			$trad = pre + $trad + $t2.trad + post;
		})*
	;
	
term returns [String trad]
	:	p1=pot {
			$trad = $p1.trad;
		} (MULOP {
			String pre = "<apply>\n";
			String post = "</apply>\n";
			if ($MULOP.text.equals("*")) {
				pre += "<times />\n";
			} else {
				pre += "<divide />\n";
			}
		} p2=pot {
			$trad = pre + $trad + $p2.trad + post;
		})*
	;
	
pot returns [String trad]
	:	f1=factor {
			$trad = $f1.trad;
		} (POTOP {
			String pre = "<apply>\n<power />\n";
			String post = "</apply>\n";
		} f2=factor {
			$trad = pre + $trad + $f2.trad + post;
		})*
	;

factor returns [String trad]
 	:	base {
                        $trad = $base.trad;
                }
        |       PARI ADDOP f1=factor PARD {
                        $trad = "<apply>\n";
                        $trad += "<times />\n";
                        $trad += "<cn>-1</cn>\n";
                        $trad += $f1.trad;
                        $trad += "</apply>\n";
                }
	|	UNARYOP PARI exp PARD {
			$trad = "<apply>\n";
			if ($UNARYOP.text.equals("ln")) {
				$trad += "<ln />\n";
			} else if ($UNARYOP.text.equals("log")) {
				$trad += "<log />\n";
			} else if ($UNARYOP.text.equals("sin")) {
				$trad += "<sin />\n";
			} else if ($UNARYOP.text.equals("cos")) {
				$trad += "<cos />\n";
			} else if ($UNARYOP.text.equals("tan")) {
				$trad += "<tan />\n";
			} else if ($UNARYOP.text.equals("asin")) {
				$trad += "<arcsin />\n";
			} else if ($UNARYOP.text.equals("acos")) {
				$trad += "<arccos />\n";
			} else if ($UNARYOP.text.equals("atan")) {
				$trad += "<arctan />\n";
			}
			$trad += $exp.trad + "</apply>\n";
		}
	;

base returns [String trad]
        :       INT {
 			$trad = "<cn>" + $INT.text + "</cn>\n";
 		}
	|	FLOAT {
			$trad = "<cn>" + $FLOAT.text + "</cn>\n";
		}
	|	ID {
			$trad = "<ci>" + $ID.text + "</ci>\n";
		}
        |	PARI exp PARD {
			$trad = $exp.trad;
		}
	|	LLAVEI exp LLAVED {
			$trad = $exp.trad;
		}
        ;

ADDOP 	:	'+' | '-'
	;
MULOP	:	'*' | '/'
	;
POTOP	:	'^'
	;
UNARYOP	:	'ln' | 'log' | 'sin' | 'cos' | 'tan' | 'asin' | 'acos' | 'atan'
	;
PARI	:	'('
	;
PARD	:	')'
	;
LLAVEI	:	'['
	;
LLAVED	:	']'
	;
COMA    :       ','
        ;
ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT :	'0'..'9'+
    ;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

